package com.fiberhome.opticalbox.ui.fragment;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.CycleInterpolator;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.TextView;

import com.fiberhome.opticalbox.R;
import com.fiberhome.airplay.jmdns.JmDNS;
import com.fiberhome.airplay.jmdns.ServiceEvent;
import com.fiberhome.airplay.jmdns.ServiceInfo;
import com.fiberhome.airplay.jmdns.ServiceListener;
import com.fiberhome.opticalbox.App;
import com.fiberhome.opticalbox.BaseFragment;
import com.fiberhome.opticalbox.C;
import com.fiberhome.opticalbox.common.FileSearchService;
import com.fiberhome.opticalbox.utils.AnimUtil;
import com.fiberhome.opticalbox.utils.BaseUtil;
import com.fiberhome.opticalbox.utils.LogUtil;
import com.fiberhome.opticalbox.view.MFrameLayout;
import com.fiberhome.opticalbox.view.SlidingMenu;

public class TvProjectionFragment extends BaseFragment {

	private TvProjectionImageFragment tvProjectionImageFragment;
	private TvProjectionVideoFragment tvProjectionVideoFragment;

	private ViewPager viewPager;
	private RadioButton rbTvProjectionImage, rbTvProjectionVideo;

	private View layTvInfoList;
	private boolean is2selectTv = false;
	private ListView listView;
	private final List<ServiceInfo> serviceList = new ArrayList<ServiceInfo>();
	private TextView txSelectedTv, txScan;
	private View layScanTv, layCurrentTvInfo;
	private ImageView imgSelectedTv;

	// the service type (which events to listen for)
	private static final String SERVICE_TYPE = "_airplay._tcp.local.";
	// the lock to enable discovery (due to saving battery)
	private MulticastLock lock;
	// JmDNS library
	private JmDNS jmdns;
	
	PagerAdapter pageAdapter ;
	
	// map of services discovered (continuously updated in background)
	private static final Map<String, ServiceInfo> services = new HashMap<String, ServiceInfo>();
	// holder for the currently selected service
	private static String selectedService = null;
	private static String selectedServiceKey = null;
	// holder for the device IP address
	private static String deviceAddress;


	public static ServiceInfo getSelectedServiceInfo() {
		if (!TextUtils.isEmpty(selectedServiceKey)) {
			return services.get(selectedServiceKey);
		}
		return null;
	}

	public static String getDeviceAddress() {
		return deviceAddress;
	}

	private MFrameLayout layContent;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.ob_fragment_tv_projection, null);

		layContent = (MFrameLayout) view;

		view.findViewById(R.id.lay_back).setOnClickListener(
				onMainBackClickListener);

		tvProjectionImageFragment = new TvProjectionImageFragment();
		tvProjectionVideoFragment = new TvProjectionVideoFragment();

		rbTvProjectionImage = (RadioButton) view
				.findViewById(R.id.rb_tv_projection_image);
		rbTvProjectionImage.setOnClickListener(onClickListener);
		rbTvProjectionImage.setChecked(true);
		rbTvProjectionVideo = (RadioButton) view
				.findViewById(R.id.rb_tv_projection_video);
		rbTvProjectionVideo.setOnClickListener(onClickListener);

		rbTvProjectionImage.setEnabled(true);
		rbTvProjectionVideo.setEnabled(true);
		
		viewPager = (ViewPager) view.findViewById(R.id.ob_viewPager);
		
		pageAdapter = new PagerAdapter(getChildFragmentManager());
		
		viewPager.setAdapter(pageAdapter);
		
		//viewPager.setAdapter(new PagerAdapter(getChildFragmentManager()));
		viewPager.setOnPageChangeListener(onPageChangeListener);


		txSelectedTv = (TextView) view.findViewById(R.id.tx_selected_tv);
		imgSelectedTv = (ImageView) view.findViewById(R.id.img_selected_tv);
		txScan = (TextView) view.findViewById(R.id.tx_scan);
		layTvInfoList = view.findViewById(R.id.lay_tv_info_list);
		layTvInfoList.setOnClickListener(onTvHiddenClickListener);
		layCurrentTvInfo = view.findViewById(R.id.lay_current_tv_info);
		layCurrentTvInfo.setOnClickListener(onTvInfoClickListener);
		view.findViewById(R.id.view_current_tv_info).setOnClickListener(
				onTvInfoClickListener);
		layScanTv = view.findViewById(R.id.lay_scan_tv);
		layScanTv.setOnClickListener(onTvScanClickListener);
		listView = (ListView) view.findViewById(R.id.ob_listView);
		listView.setAdapter(adapter);
		listView.setOnItemClickListener(onItemClickListener);

		bindFileSearchService();

		startScanTvInfoList();

		return view;
	}

	private OnClickListener onClickListener = new OnClickListener() {
		@Override
		public void onClick(View view) {
			switch (view.getId()) {
			case R.id.rb_tv_projection_image:
				
				viewPager.setAdapter(pageAdapter);
				rbTvProjectionVideo.setTextColor(Color.parseColor("#777777"));
				rbTvProjectionImage.setChecked(true);
				rbTvProjectionImage.setTextColor(Color.parseColor("#FFFFFF"));
				
				viewPager.setCurrentItem(0);
				//pageAdapter.notifyDataSetChanged();
				break;
			case R.id.rb_tv_projection_video:
				viewPager.setCurrentItem(1);
				break;
			}
		}
	};

	private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {
		@Override
		public void onPageSelected(int position) {

			rbTvProjectionImage.setTextColor(Color.parseColor("#777777"));
			rbTvProjectionVideo.setTextColor(Color.parseColor("#777777"));
			switch (position) {
			case 0:
				rbTvProjectionImage.setChecked(true);
				rbTvProjectionImage.setTextColor(Color.parseColor("#FFFFFF"));
				break;
			case 1:
				rbTvProjectionVideo.setChecked(true);
				rbTvProjectionVideo.setTextColor(Color.parseColor("#FFFFFF"));
				break;
			}
		}

		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {
		}

		private static final int STATE_RELEASE_MOVE = 2;
		private static final int STATE_MOVE_OVER = 0;

		@Override
		public void onPageScrollStateChanged(int state) {
			if (state == STATE_RELEASE_MOVE) {
				layContent.setIntercept(true);
			} else if (state == STATE_MOVE_OVER) {
				layContent.setIntercept(false);
			}
		}
	};

	public class PagerAdapter extends FragmentPagerAdapter {

		public PagerAdapter(FragmentManager fm) {
			super(fm);
		}

		@Override
		public CharSequence getPageTitle(int position) {
			return "fragment[" + position + "]";
		}

		@Override
		public int getCount() {
			return 2;
		}

		@Override
		public Fragment getItem(int position) {
			switch (position) {
			case 0:
				return tvProjectionImageFragment;
			case 1:
				return tvProjectionVideoFragment;
			default:
				return null;
			}
		}
	}

	private void bindFileSearchService() {
		if (holder != null) {
			Intent intent = new Intent(holder, FileSearchService.class);
			holder.bindService(intent, mServiceConnection,
					Activity.BIND_AUTO_CREATE);
		}

	}

	private void unBindFileSearchService() {
		if (holder != null) {
			holder.unbindService(mServiceConnection);
		}
	}

	private final ServiceConnection mServiceConnection = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName componentName,
				IBinder service) {
			final FileSearchService fileSearchService = ((FileSearchService.LocalBinder) service)
					.getService();

			handler.postDelayed(new Runnable() {
				@Override
				public void run() {
					fileSearchService.startSearch();
				}
			}, SlidingMenu.ANIM_TIME);
		}

		@Override
		public void onServiceDisconnected(ComponentName componentName) {
		}
	};

	private void startScanTvInfoList() {
		if (holder != null) {
			if (lock != null) {
				lock.release();
				lock = null;
			}
			WifiManager wifi = (WifiManager) holder
					.getSystemService(android.content.Context.WIFI_SERVICE);
			lock = wifi.createMulticastLock("JmDNSLock");
			lock.setReferenceCounted(true);
			lock.acquire();
		}

		txScan.setText(R.string.ob_scan_1);
		layScanTv.setOnClickListener(null);
		txScan.postDelayed(new Runnable() {
			@Override
			public void run() {
				txScan.setText(R.string.ob_scan);
				layScanTv.setOnClickListener(onTvScanClickListener);
			}
		}, 8000);

		txSelectedTv.setText(R.string.ob_scan_3);
		services.clear();
		serviceList.clear();
		adapter.notifyDataSetChanged();

		// JmDNS
		Thread thread = new Thread() {
			@Override
			public void run() {
				try {
					// device address
					// local ip address
					deviceAddress = getWifiIpLocalAddress();
					if (deviceAddress == null) {
						LogUtil.e("Error: Unable to get local IP address");
						return;
					}
					// init jmdns
					if (jmdns != null) {
						try {
							jmdns.removeServiceListener(SERVICE_TYPE,
									serviceListener);
							jmdns.close();
							jmdns = null;
						} catch (Exception e) {
							LogUtil.e("Error: " + e.getMessage());
						}
					}
					
					selectedService = null;
					selectedServiceKey = null;

					jmdns = JmDNS.create(deviceAddress);
					jmdns.addServiceListener(SERVICE_TYPE, serviceListener);
					LogUtil.e("Using local address " + deviceAddress);
				} catch (Exception e) {
					LogUtil.e("Error: " + e.getMessage() == null ? "Unable to initialize discovery service"
							: e.getMessage());
				}
			}
		};
		thread.start();
	}

	private String getWifiIpLocalAddress() {
		if (holder != null) {
			WifiManager wifiManager = (WifiManager) holder
					.getSystemService(Context.WIFI_SERVICE);
			WifiInfo wifiConnectInfo = wifiManager.getConnectionInfo();
			return intToIp(wifiConnectInfo.getIpAddress());
		}
		return null;
	}

	private String intToIp(int i) {
		return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF)
				+ "." + ((i >> 24) & 0xFF);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();

		unBindFileSearchService();
		
		// JmDNS
		if (jmdns != null) {
			try {
				jmdns.removeServiceListener(SERVICE_TYPE, serviceListener);
				jmdns.close();
				jmdns = null;
			} catch (Exception e) {
				LogUtil.e("Error to release jmdns : " + e.getMessage());
			}
		}

		// release multicast lock
		if (lock != null) {
			lock.release();
		}
	}

	private OnItemClickListener onItemClickListener = new OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,
				long id) {
			//final String lastSelectedServiceKey = selectedServiceKey;

			selectedService = serviceList.get(position).getName();
			selectedServiceKey = serviceList.get(position).getKey();
			txSelectedTv.setText(selectedService);

			if (holder != null) {
				SharedPreferences prefs = holder.getSharedPreferences(
						getString(R.string.app_name), Context.MODE_PRIVATE);
				prefs.edit().putString(C.sp.selectedTv, selectedService)
						.commit();

				//if(null != lastSelectedServiceKey){
				//	if (TextUtils.isEmpty(lastSelectedServiceKey)
				//			&& !lastSelectedServiceKey.equals(selectedServiceKey)) {
				//		App.setVideoFlags(true);
				//	}
				//}
			}

			hiddenTvInfoList();
		}
	};

	private ServiceListener serviceListener = new ServiceListener() {
		@Override
		public void serviceAdded(final ServiceEvent event) {
			LogUtil.e("seviceListener serviceAdded()" + event.getName());
			// services.put(event.getInfo().getKey(), event.getInfo());
			handler.post(new Runnable() {
				@Override
				public void run() {
					LogUtil.e("seviceListener serviceAdded() requestServiceInfo " + event.getName());
					jmdns.requestServiceInfo(event.getType(), event.getName(),
							1000);
				}
			});
		}

		@Override
		public void serviceRemoved(ServiceEvent event) {
			LogUtil.e("seviceListener serviceRemoved()" + event.getName());
			services.remove(event.getInfo().getKey());
			if (selectedService != null
					&& selectedService.equals(event.getName())) {
				selectedService = null;
				selectedServiceKey = null;
				handler.post(new Runnable() {
					@Override
					public void run() {
						txSelectedTv.setText(R.string.ob_selected_tv_1);
						App.setVideoFlags(true);
					}
				});
			}

			resetServiceList();
		}

		@Override
		public void serviceResolved(final ServiceEvent event) {
			LogUtil.e("seviceListener serviceResolved()" + event.getName());
			services.put(event.getInfo().getKey(), event.getInfo());
			if (selectedService == null) {
				if (holder != null) {
					SharedPreferences prefs = holder.getSharedPreferences(
							getString(R.string.app_name), Context.MODE_PRIVATE);
					String remembered = prefs.getString(C.sp.selectedTv, null);
					if (remembered != null
							&& remembered.equals(event.getInfo().getName())) {
						selectedService = remembered;
						selectedServiceKey = event.getInfo().getKey();
						handler.post(new Runnable() {
							@Override
							public void run() {
								txSelectedTv.setText(selectedService);
							}
						});
					}
				}
			}

			resetServiceList();
		}
	};

	private void resetServiceList() {
		handler.post(new Runnable() {
			@Override
			public void run() {
				serviceList.clear();
				for (String key : services.keySet()) {
					serviceList.add(services.get(key));
				}

				adapter.notifyDataSetChanged();
			}
		});
	}

	private BaseAdapter adapter = new BaseAdapter() {
		class ViewHolder {
			TextView textView;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder viewHolder;
			if (convertView != null) {
				viewHolder = (ViewHolder) convertView.getTag();
			} else {
				viewHolder = new ViewHolder();
				convertView = LayoutInflater.from(holder).inflate(
						R.layout.ob_list_content_tv_info, null);
				viewHolder.textView = (TextView) convertView
						.findViewById(R.id.ob_textView);
				convertView.setTag(viewHolder);
			}

			viewHolder.textView.setText(serviceList.get(position).getName());
			return convertView;
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public Object getItem(int position) {
			return serviceList.get(position);
		}

		@Override
		public int getCount() {
			return serviceList.size();
		}
	};

	private void showTvInfoList() {
		is2selectTv = true;
		layTvInfoList.setVisibility(View.VISIBLE);
		layTvInfoList.startAnimation(AnimUtil.init()
				.addTranslate(0, 0, -layTvInfoList.getHeight(), 0).create());

		layTvInfoList.setOnClickListener(onTvHiddenClickListener);

		imgSelectedTv.setImageResource(R.drawable.ob_arrow_top);
	}

	private void hiddenTvInfoList() {
		is2selectTv = false;
		layTvInfoList.startAnimation(AnimUtil.init()
				.addTranslate(0, 0, 0, -layTvInfoList.getHeight()).create());
		layTvInfoList.setVisibility(View.GONE);

		layTvInfoList.setOnClickListener(null);

		imgSelectedTv.setImageResource(R.drawable.ob_arrow_bottom);
	}

	private OnClickListener onTvInfoClickListener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			LogUtil.d("onTvInfoClickListener");
			if (!is2selectTv) {
				showTvInfoList();
			} else {
				hiddenTvInfoList();
			}
		}
	};

	private OnClickListener onTvScanClickListener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			startScanTvInfoList();
		}
	};

	private OnClickListener onTvHiddenClickListener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			hiddenTvInfoList();
		}
	};

	public void animTitleInfoShake() {
		layCurrentTvInfo.clearAnimation();
		layCurrentTvInfo.startAnimation(AnimUtil
				.init()
				.addTranslate(0, BaseUtil.dip2px(holder, 5), 0, 0, 0, 800,
						new CycleInterpolator(5)).create());
	}
}
